package guowei.gulielasticsearch.controller;

import guowei.common.utils.Constant;
import guowei.common.utils.R;
import guowei.gulielasticsearch.EsConstant.ProductConstant;
import guowei.gulielasticsearch.config.GuliEs;
import guowei.gulielasticsearch.vo.SearchParam;
import guowei.gulielasticsearch.vo.SearchResult;
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;

import javax.swing.*;
import java.io.IOException;
import java.util.List;

public class EsSearchGuli {

    @Autowired
    private RestHighLevelClient client;

    public R RestEs(SearchParam searchParam){
        SearchRequest searchRequest = null;
        SearchResult searchResult = null;

//        1.准备检索请求                  方法1
        searchRequest = requestBinding(searchParam);

//        2.执行检索数据
        try {
            client.search(searchRequest, GuliEs.COMMON_OPTIONS);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

//        3.分析响应数据
        searchResult = gainData(searchRequest);
        return R.ok();
    }

    /**
     * 构建结果数据的方法
     * @param searchRequest
     * @return
     */
    private SearchResult gainData(SearchRequest searchRequest) {
        SearchResult searchResult = null;
        return searchResult;
    }

    /**
     * 构建请求的方法
     * @return
     */
    private SearchRequest requestBinding(SearchParam searchParam) {

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();   //创建dsl语句都从此builder得到
// 1构建bool - query
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();     //创建query下的bool查询
// 1.1 must模糊匹配
        if (!StringUtils.isEmpty(searchParam.getKeyword())){
            boolQuery.must(QueryBuilders.matchQuery("skuTitle",searchParam.getKeyword()));
        }

// 1.2 filter过滤内容  term类型, 根据catalog3Id匹配
        if (!StringUtils.isEmpty(searchParam.getCatalog3Id())){
            boolQuery.filter(QueryBuilders.termQuery("catalog3Id",searchParam.getCatalog3Id()));
        }

// 1.3 根据brandId过滤 terms类型，
        if (!StringUtils.isEmpty(searchParam.getBrandId())){
            boolQuery.filter(QueryBuilders.termsQuery("brandId",searchParam.getBrandId()));
        }

// 1.4 根据hasStock过滤 term类型  按照库存查询为true则查有库存的 若为false则查无库存的
            boolQuery.filter(QueryBuilders.termQuery("hasStock",searchParam.getHasStock()==1));

// 1.5 根据skuPrice过滤 range类型  我们规定传参时一定按照如下格式  100_500  _500  100_
        if (!StringUtils.isEmpty(searchParam.getSkuPrice())){
            String skuPrice = searchParam.getSkuPrice();
            String[] price = skuPrice.split("_");
            if (price.length == 2){
                if (StringUtils.isEmpty(price[0])){
                    boolQuery.filter(QueryBuilders.rangeQuery("skuPrice").lte(price[1]));
                }else {
                    boolQuery.filter(QueryBuilders.rangeQuery("skuPrice").gte(price[0]).lte(price[1]));
                }
            }else if(price.length == 1){
                boolQuery.filter(QueryBuilders.rangeQuery("skuPrice").gte(price[0]));
            }
        }

// 1.6 根据nested的attrs属性过滤   按照 attrs=1_6寸:12寸&attrs=2_7寸:13寸 格式来表示attrs属性
        if (searchParam.getAttrs() != null & searchParam.getAttrs().size() > 0){
            List<String> attrs = searchParam.getAttrs();
            for (String attr: attrs) {

                BoolQueryBuilder nestedboolQueryBuilder = QueryBuilders.boolQuery();   //构建一个BoolQueryBuilder

                String[] split = attr.split("_");
                nestedboolQueryBuilder.must(QueryBuilders.termQuery("attrs.attrId",split[0]));
                String[] split1 = split[1].split(":");
                nestedboolQueryBuilder.must(QueryBuilders.termsQuery("attrs.attrValue",split1));
                //每一个attrs都生成一个nested查询
                QueryBuilders.nestedQuery("attrs",nestedboolQueryBuilder,ScoreMode.None);     //ScoreMode.None表示不参与评分
            }
        }
//  2.1 将封装好的boolQuery语句包装进searchSourceBuilder里面
        searchSourceBuilder.query(boolQuery);

//  2.2排序  按照 sort=hotScore_asc/desc
        if (!StringUtils.isEmpty(searchParam.getSort())){
            String[] split = searchParam.getSort().split("_");
            String order = split[1];
            SortOrder sortOrder = ("asc".equalsIgnoreCase(order)?SortOrder.ASC:SortOrder.DESC);
            searchSourceBuilder.sort("skuId",sortOrder);
        }

//   2.3分页  按照pageNum查询   pageNum:5    默认值为1
        searchSourceBuilder.from((searchParam.getPageNum() - 1) * ProductConstant.PRODUCT_SIZE);
        searchSourceBuilder.size(ProductConstant.PRODUCT_SIZE);

//    2.4高亮,前提是match的skuTitle里面检索的有数据
        if (!StringUtils.isEmpty(searchParam.getKeyword())){
            HighlightBuilder highlightBuilder = new HighlightBuilder();
            highlightBuilder.field("skuTitle");
            highlightBuilder.preTags("<b style='color:red'>");
            highlightBuilder.postTags("</b>");
            //执行高亮语句
            searchSourceBuilder.highlighter(highlightBuilder);
        }

//    3.聚合分析


//    4.得到构建的dsl语句
        String s = searchSourceBuilder.toString();
        System.out.println("构建的dsl语句为为/n"+s);

//将构建好的searchRequest返回
        SearchRequest searchRequest = new SearchRequest(new String[]{ProductConstant.PRODUCT_INDEX}, searchSourceBuilder);
        return searchRequest;
    }
}